// 简介
// 示例：将数组中的数翻倍
// 方式1：命令式编程
// const numbers = [1, 2, 3, 4, 5];
// console.log(numbers); 
// const doubledNumbers = [];
// for (let i = 0; i < numbers.length; i++) {
//   doubledNumbers.push(numbers[i] * 2);
// }
// console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]

// 方式2：函数式编程：高阶函数map和匿名函数
// const numbers = [1, 2, 3, 4, 5];
// console.log(numbers);
// const doubledNumbers = numbers.map(num => num * 2);
// console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]

// 函数表达式

// 方式1：显式定义函数
// const sum = function total(x, y){
//     return x+y;
// };
// console.log(sum(3,2));
// console.log(total(3,2));

// 方式2：匿名函数
// const sum = function (x, y){
//     return x+y;
// };
// console.log(sum(3,2));

// 示例：把匿名函数当做参数传递给数组方法
// const numbers = [1, 2, 3, 4, 5, 6, 7];
// const evens = numbers.filter(function (x) {
//   return x % 2 === 0;
// });

// console.log(evens); // Outputs: [2, 4, 6]

// 第2讲-函数作为方法
// 方式1：
// const account = {
//   balance: 100,
//   deposit: function(amount) {
//     this.balance += amount;
//   },
//   withdraw: function(amount) {
//     this.balance -= amount;
//   }
// }

// account.deposit(50);
// account.withdraw(20);
// console.log(account.balance); // Output: 130

// 方式2
// const account = {
//   balance: 100,

//   deposit(amount) {
//     this.balance += amount;
//   },

//   withdraw(amount) {
//     this.balance -= amount;
//   }
// }

// account.deposit(50);
// account.withdraw(20);
// console.log(account.balance); // Output: 130

// 第3讲-箭头函数

// const mean = (x, y) => {
//   return (x + y) / 2;
// };

// const user = username => ({ username });
// This simplifies:
// const user = (username) => {
//   return { username };
// };

// const numbers = [1, 2, 3, 4, 5, 6, 7];
// const evens = numbers.filter(x => x % 2 === 0);
// console.log(evens); // Outputs: [2, 4, 6]

// 第04讲-内部函数

// function outer() {
//   let a = 1;

//   function inner() {
//     let a = 2;
//     let b = 3;
//     console.log(a); // Prints 2
//     console.log(b); // Prints 3
//   }

//   inner();
//   console.log(a); // Prints 1
//   console.log(b); // ReferenceError: b is not defined
// }

// outer();

// 第05讲-函数currying

// 方式1：
// function makeSundae(base, topping) {
//   return `Here is your ${base} ice cream with ${topping}!`;
// }

// const sundae = makeSundae("vanilla", "hot fudge");
// console.log(sundae);

// 方式2：
// function makeSundae(base) {
//   return function (topping) {
//     return `Here is your ${base} ice cream with ${topping}!`;
//   }
// }

// const vanillaSundae = makeSundae("vanilla");
// const chocolateSundae = makeSundae("chocolate");

// console.log(chocolateSundae("hot fudge"));
// console.log(vanillaSundae("chocolate syrup"));


// 示例：计算对数
// function makeLog(base) {
//   return function(value) {
//     return Math.log(value) / Math.log(base);
//   }
// }

// const log10 = makeLog(10);
// const log2 = makeLog(2);

// console.log(log10(100));  // Output: 2
// console.log(log2(8));     // Output: 3

// 第6讲：函数闭包
// function counter(step = 1) {
//   let count = 0;
//   return function increaseCount() {
//     count += step;
//     return count;
//   }
// }

// const incBy1 = counter();
// const incBy10 = counter(10);

// console.log(incBy1());  // Output: 1
// console.log(incBy1());  // Output: 2

// console.log(incBy10()); // Output: 10
// console.log(incBy10()); // Output: 20

// 第07讲-函数复合

// 示例1：
// function double(x) {
//   return x * 2;
// }

// function increment(x) {
//   return x + 1;
// }

// // Compose function to apply increment then double
// function compose(f, g) {
//   return function(x) {
//     return f(g(x));
//   };
// }

// const incrementAndDouble = compose(double, increment);

// console.log(incrementAndDouble(3)); // Output: 8

function lowerCase(input) {
  return input.toLowerCase();
}

function trim(input) {
  return input.trim();
}

function wrapInDiv(input) {
  return `<div>${input}</div>`;
}

// function compose(f, g, h) {
//   return function(x) {
//     return f(g(h(x)));
//   };
// }

function compose(...funcs) {
  return funcs.reduce((a, b) => (...args) => a(b(...args)));
}

// Compose functions to prepare text
const prepareText = compose(wrapInDiv, lowerCase, trim);

console.log(prepareText("  Hello World  ")); // Output: <div>hello world</div>